package com.evon.yardmanagement.dao;

import java.sql.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.evon.yardmanagement.exception.YardManagementException;
import com.evon.yardmanagement.exception.YardManagementException.ExceptionType;
import com.evon.yardmanagement.model.Car;
import com.evon.yardmanagement.model.Member;
import com.evon.yardmanagement.model.ParkingSlot;
import com.evon.yardmanagement.model.Transporter;

public class CarDAO extends BaseHibernateDAO {
	private static final Log log = LogFactory.getLog(CarDAO.class);

	@Override
	public Class getQueryClass() {
		// TODO Auto-generated method stub
		return Car.class;
	}

	public List<Car> findCar(String chasisNumber, int yardId) {
		log.debug("finding  car with chasis number: " + chasisNumber
				+ " in yard: " + yardId);
		try {
			Criteria criteria = getSession().createCriteria(getQueryClass());
			criteria.add(Restrictions.eq("carChasisNumber", chasisNumber));
			criteria.add(Restrictions.eq("yardId", yardId));

			return criteria.list();
		} catch (HibernateException re) {
			log.error("find by property name failed", re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("find by property name failed", rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}

	
	public List<ParkingSlot> getAvailableParkingForSection(int sectionId) {
		try {
			Criteria criteria = getSession().createCriteria(ParkingSlot.class)
					.createAlias("section", "section");
			criteria.add(Restrictions.eq("section.id", sectionId));
			// criteria.add(Restrictions.eq("section.isPermanent", 1));
			criteria.add(Restrictions.eq("occupied", 0));
			criteria.addOrder(Order.asc("priority"));
			return criteria.list();
		} catch (HibernateException re) {
			log.error("Hibernate exception in getAvailableParkingForSection",
					re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("Hibernate exception in getAvailableParkingForSection",
					rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}

	public static void main(String as[]) {
		new ParkingSlotDAO().markParkingSlotOccupied(1);
	}

	public Car markForRetrieval(int carId) {
		try {
			Car car = (Car) getSession().load(getQueryClass(), carId);
			car.setRetrievalFlag('Y');
			save(car);
			return car;
		} catch (HibernateException re) {
			log.error("Hibernate exception while markForRetrieval", re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("Hibernate exception while markForRetrieval", rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}

	/**
	 * Retrieve the car, so set retrieval time and parking status.
	 * 
	 * @param id
	 */
	public Car confirmCarRetrieval(int id) {
		try {
			Car car = (Car) getSession().get(getQueryClass(), id);
			car.setRetrievalTime(new Date(new java.util.Date().getTime()));
			car.setParkingStatus("R");
			save(car);
			return car;
		} catch (HibernateException re) {
			log.error("Hibernate exception while reteieveCar", re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("Hibernate exception while reteieveCar", rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}
	
	/**
	 * Set the retrieval request for the car.
	 * Set the retrieval flag to Y and set the retrieval driver.
	 * 
	 * @param id
	 */
	public Car markForRetrieval(int id, Integer retrievalMemberId) {
		try {
			Car car = (Car) getSession().get(getQueryClass(), id);
			car.setRetrievalFlag('Y');
			car.setRetrievalDriver((Member) getSession().load(Member.class,
					retrievalMemberId));
			save(car);
			return car;
		} catch (HibernateException re) {
			log.error("Hibernate exception while reteieveCar", re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("Hibernate exception while reteieveCar", rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}
	
	

	public Car assignTransporter(int id, int selectedTransporterId) {
		try {
			Car car = (Car) getSession().get(getQueryClass(), id);
			if(car == null){
				return null;
			}
			car.setTransporter((Transporter) getSession().load(
					Transporter.class, selectedTransporterId));
			 save(car);
			 return car;
		} catch (HibernateException re) {
			log.error("Hibernate exception while assignTransporter", re);
			throw new YardManagementException(re, ExceptionType.RECOVERABLE);
		} catch (RuntimeException rex) {
			log.error("Hibernate exception while assignTransporter", rex);
			throw new YardManagementException(rex, ExceptionType.RECOVERABLE);
		}

	}

}
